/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2021-2022. All rights reserved.
 *
 */

import { AbilityTypeEnum } from '../../enum/ability-type-enum.js';
import { CodeType } from '../../enum/code-type-enum.js';
import { ConfigJson } from '../../options/configure/config-json-options.js';

import { LegacyAbilityModel } from './legacy-ability-model.js';
import ConfigOptObj = ConfigJson.ConfigOptObj;
import { resModelLoader } from '../../utils/loader/file/res-model-loader.js';
import { OhosLogger } from '../../utils/log/ohos-logger.js';

/**
 * Fa模型中的ability数据模型
 *
 * @since 2022/1/19
 */
export class LegacyAbilityModelImpl implements LegacyAbilityModel {
  private _log: OhosLogger = OhosLogger.getLogger(LegacyAbilityModelImpl.name);

  private readonly _configObj: ConfigOptObj;
  private readonly _configFile: string;
  private readonly _abilityName: string;
  private readonly _abilityObj: ConfigJson.AbilitiesObj;
  private readonly _jsObj: ConfigJson.JsObj | undefined;

  constructor(configJson: string, abilityName: string) {
    this._configObj = resModelLoader.getConfigJson(configJson);
    this._configFile = configJson;
    this._abilityName = abilityName;
    this._abilityObj = this.findAbilityByName();
    this._jsObj = this.findJsByName();
  }

  private findJsByName(): ConfigJson.JsObj | undefined {
    if (!this._abilityObj || !this.hasJsObj()) {
      return undefined;
    }

    const jsObjs: ConfigJson.JsObj[] = this._configObj.module.js ?? [];
    for (const jsObj of jsObjs) {
      if (jsObj.name !== this._abilityName) {
        continue;
      }
      return jsObj;
    }
    this._log.printErrorExit(
      'PAGE_ABILITY_REQUIRE_JS_COMPONENT',
      [this._configFile],
      [[this._abilityName]]
    );
    return undefined;
  }

  private hasJsObj() {
    // page需要有对应js页面
    return this.getType() === AbilityTypeEnum.PAGE;
  }

  private findAbilityByName(): ConfigJson.AbilitiesObj {
    const abilityObjs: ConfigJson.AbilitiesObj[] = this._configObj.module.abilities ?? [];
    for (const abilityObj of abilityObjs) {
      if (abilityObj.name !== this._abilityName) {
        continue;
      }
      return abilityObj;
    }
    this._log.printErrorExit(
      'ABILITY_NAME_NOT_EXIST',
      [this._abilityName],
      [[this._configFile]]
    );

    throw new Error('Internal error.');
  }

  getRelateSrcPath(): string {
    const srcPath: string | undefined = this._abilityObj.srcPath;
    return srcPath === undefined ? this.getName() : srcPath;
  }

  getName(): string {
    return this._abilityName;
  }

  getSrcLanguage(): CodeType {
    return this._abilityObj.srcLanguage as CodeType;
  }

  getType(): AbilityTypeEnum {
    return AbilityTypeEnum.valueOf(this._abilityObj);
  }

  getConfigJsonJsObj(): ConfigJson.JsObj | undefined {
    return this._jsObj;
  }
}
